package com.youdoneed.user.admin;

import com.querydsl.sql.SQLQuery;
import com.querydsl.sql.SQLQueryFactory;
import com.querydsl.sql.dml.SQLInsertClause;
import com.youdoneed.base.application.AppException;
import com.youdoneed.base.common.AESEncryptor;
import com.youdoneed.base.common.GlobalIdWorker;
import com.youdoneed.base.pagination.Page;
import com.youdoneed.base.pagination.Paging;
import com.youdoneed.user.application.QueryHelper;
import com.youdoneed.user.model.Admin;
import com.youdoneed.user.model.AdminRole;
import com.youdoneed.user.model.Authority;
import com.youdoneed.user.model.Role;
import com.youdoneed.user.query.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * 管理员服务类接口实现类
 *
 * @author Ewing
 * @date 2017年2月8日
 */
@Service
@Transactional
public class AdminServiceImpl implements AdminService {

    @Autowired
    private SQLQueryFactory queryFactory;
    // 约定查询对象以大写开头
    private QAdmin qAdmin = QAdmin.Admin;
    private QAdminRole qAdminRole = QAdminRole.AdminRole;
    private QRole qRole = QRole.Role;
    private QRoleAuthority qRoleAuthority = QRoleAuthority.RoleAuthority;
    private QAuthority qAuthority = QAuthority.Authority;

    /**
     * 管理员登录
     */
    @Override
    public Admin adminLogin(String account, String password) {
        if (!StringUtils.hasText(account) || !StringUtils.hasText(password)) {
            throw new AppException("账号或密码不能为空！");
        }

        // 明文密码查询前加密
        password = AESEncryptor.encryptString(password);

        return queryFactory.selectFrom(qAdmin)
                .where(qAdmin.account.eq(account))
                .where(qAdmin.password.eq(password))
                .fetchOne();
    }

    /**
     * 管理员密码重置
     */
    @Override
    public Admin resetPassword(String adminId, String oldPassword, String newPassword) {
        // 参数防空判断。
        if (!StringUtils.hasText(adminId)) {
            throw new AppException("管理员ID不能为空。");
        }
        if (!StringUtils.hasText(oldPassword)) {
            throw new AppException("旧密码不能为空。");
        }
        if (!StringUtils.hasText(newPassword)) {
            throw new AppException("新密码不能为空。");
        }
        if (oldPassword.equals(newPassword)) {
            throw new AppException("新密码不能和旧密码相同。");
        }

        Admin admin = findByAdminId(adminId);
        if (admin == null) {
            throw new AppException("该管理员不存在或已删除。");
        }

        // 对旧密码进行加密比对
        oldPassword = AESEncryptor.encryptString(oldPassword);
        if (!oldPassword.equals(admin.getPassword())) {
            throw new AppException("旧密码不正确！");
        }

        // 对新密码进行加密存储
        newPassword = AESEncryptor.encryptString(newPassword);

        // 只更新密码
        queryFactory.update(qAdmin)
                .set(qAdmin.password, newPassword)
                .where(qAdmin.adminId.eq(adminId))
                .execute();

        return admin;
    }

    @Override
    public Admin findByAdminId(String adminId) {
        if (!StringUtils.hasText(adminId)) {
            throw new AppException("管理员ID不能为空。");
        }
        return queryFactory.selectFrom(qAdmin)
                .where(qAdmin.adminId.eq(adminId))
                .fetchOne();
    }

    /**
     * 添加管理员
     */
    @Override
    public Admin addAdmin(Admin admin, String[] roleIds) {
        if (admin == null) {
            throw new AppException("管理员对象不能为空。");
        }
        if (!StringUtils.hasText(admin.getName())) {
            throw new AppException("管理员名称不能为空。");
        }
        if (!StringUtils.hasText(admin.getAccount())) {
            throw new AppException("管理员账号不能为空。");
        }
        if (!StringUtils.hasText(admin.getPassword())) {
            throw new AppException("管理员密码不能为空。");
        }

        //防止重复添加管理员用户
        if (queryFactory.selectFrom(qAdmin)
                .where(qAdmin
                        .account.eq(admin.getAccount()))
                .fetchCount() > 0) {
            throw new AppException("该管理员帐号已存在！");
        }

        // 缺省属性给默认值。
        if (admin.getGender() == null) {
            admin.setGender(0);
        }
        admin.setAdminId(GlobalIdWorker.nextString());
        admin.setCreateTime(new Date());
        // 密码需要加密存储
        String password = AESEncryptor.encryptString(admin.getPassword());
        admin.setPassword(password);

        //保存实体对象
        queryFactory.insert(qAdmin)
                .populate(admin)
                .execute();

        // 新增管理员角色关系
        adminAddRoles(admin, roleIds);
        return admin;
    }

    /**
     * 给管理员添加权限。
     *
     * @param admin   管理员。
     * @param roleIds 权限ID。
     */
    private void adminAddRoles(Admin admin, String[] roleIds) {
        //查找所有角色，并保存角色与管理员的关联关系
        if (roleIds != null && roleIds.length > 0) {
            SQLInsertClause insertAdminRole = queryFactory.insert(qAdminRole);
            for (String roleId : roleIds) {
                Role role = queryFactory.selectFrom(qRole)
                        .where(qRole.roleId.eq(roleId))
                        .fetchOne();
                if (role == null) {
                    continue;
                }
                AdminRole adminRole = new AdminRole();
                adminRole.setAdminId(admin.getAdminId());
                adminRole.setRoleId(role.getRoleId());
                adminRole.setCreateTime(new Date());
                insertAdminRole.populate(adminRole).addBatch();
            }
            if (!insertAdminRole.isEmpty()) {
                insertAdminRole.execute();
            }
        }
    }

    @Override
    public Page<Admin> findAdminByName(String name, Paging paging) {
        // 查询管理员
        SQLQuery<Admin> query = queryFactory.selectFrom(qAdmin)
                .where(qAdmin.name.contains(name))
                .orderBy(qAdmin.createTime.asc());
        // 分页查询数据
        Page<Admin> adminPage = QueryHelper.queryPage(paging, query);

        // 获取每个管理员的角色
        for (Admin admin : adminPage.getContent()) {
            List<Role> roles = queryFactory.selectFrom(qRole)
                    .leftJoin(qAdminRole).on(qRole.roleId.eq(qAdminRole.roleId))
                    .where(qAdminRole.adminId.eq(admin.getAdminId()))
                    .fetch();
            admin.setRoles(roles);
        }
        return adminPage;
    }

    @Override
    public Admin updateAdmin(Admin admin, String[] roleIds) {
        if (admin == null || !StringUtils.hasText(admin.getAdminId())) {
            throw new AppException("选择需要修改的管理员。");
        }
        Admin oldAdmin = findByAdminId(admin.getAdminId());
        if (oldAdmin == null) {
            throw new AppException("该管理员不存在或已删除。");
        }

        // 缺省属性给默认值。
        oldAdmin.setName(admin.getName());
        oldAdmin.setGender(admin.getGender());
        oldAdmin.setAdminState(admin.getAdminState());

        queryFactory.update(qAdmin)
                .populate(oldAdmin)
                .where(qAdmin.adminId.eq(oldAdmin.getAdminId()))
                .execute();

        //删除管理员角色关系
        queryFactory.delete(qAdminRole)
                .where(qAdminRole.adminId.eq(admin.getAdminId()))
                .execute();

        //新增管理员角色关系
        adminAddRoles(oldAdmin, roleIds);
        return oldAdmin;
    }

    @Override
    public List<Authority> getAuthorityMenus(String adminId) {
        // 查询管理员的所有权限
        SQLQuery<Authority> queryAuthority = queryFactory
                .selectDistinct(qAuthority)
                .from(qAuthority)
                .leftJoin(qRoleAuthority).on(qAuthority.authorityId.eq(qRoleAuthority.authorityId))
                .leftJoin(qAdminRole).on(qRoleAuthority.roleId.eq(qAdminRole.roleId))
                .where(qAdminRole.adminId.eq(adminId))
                .where(qAuthority.status.eq(1))
                .orderBy(qAuthority.sorter.asc());
        // 限制只查父权限
        List<Authority> authorities = queryAuthority.clone(queryFactory.getConnection())
                .where(qAuthority.type.eq(2))
                .where(qAuthority.superId.isNull())
                .fetch();
        // 逐个查询子权限菜单
        for (Authority authority : authorities) {
            // 限制只查子权限
            List<Authority> subAuthorities = queryAuthority.clone(queryFactory.getConnection())
                    .where(qAuthority.superId.eq(authority.getAuthorityId()))
                    .fetch();
            authority.setSubAuthorities(subAuthorities);
        }
        return authorities;
    }

    @Override
    public void deleteAdmin(Admin admin) {
        if (admin == null || !StringUtils.hasText(admin.getAdminId())) {
            throw new AppException("选择需要删除的管理员。");
        }

        //删除管理员角色关系
        queryFactory.delete(qAdminRole)
                .where(qAdminRole.adminId.eq(admin.getAdminId()))
                .execute();

        //删除管理员对象
        queryFactory.delete(qAdmin)
                .where(qAdmin.adminId.eq(admin.getAdminId()))
                .execute();
    }

}
